#include "internalflash.h"

// 从指定地址读flash指定长度的数据保存到缓冲区
void ReadFlashData(uint32_t ReadAddress, uint8_t *data, uint32_t length)
{
    for(uint32_t i=0;i<length;i++) {
        data[i]=*(uint8_t*)(ReadAddress+i); //读取数据
    }
}

// 根据输入的地址给出它所在的sector
static uint32_t STMFLASH_ReadWord(uint32_t faddr)
{
    return *(uint32_t*)faddr;
}

// 根据输入的地址给出它所在的sector
uint32_t GetSector(uint32_t Address)
{
	uint32_t sector = 0;

	if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0)) {
		sector = FLASH_SECTOR_0;
	} else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1)) {
		sector = FLASH_SECTOR_1;
	}else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2)) {
		sector = FLASH_SECTOR_2;
	} else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3)) {
		sector = FLASH_SECTOR_3;
	} else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4)) {
		sector = FLASH_SECTOR_4;
	} else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5)) {
		sector = FLASH_SECTOR_5;
	} else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6)) {
		sector = FLASH_SECTOR_6;
	} else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7)) {
		sector = FLASH_SECTOR_7;
	} else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8)) {
		sector = FLASH_SECTOR_8;
	} else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9)) {
		sector = FLASH_SECTOR_9;
	} else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10)) {
		sector = FLASH_SECTOR_10;
	} else {
		sector = FLASH_SECTOR_11;
	}
	return sector;
}

/**
 *@功能：向内部Flash写入数据
 *@参数1：WriteAddress：数据要写入的目标地址（偏移地址）
 *@参数2：*data： 写入的数据首地址
 *@参数3：length：写入数据的个数
 */
void WriteFlashData(uint32_t WriteAddress, uint8_t *data, uint32_t length)
{
	FLASH_EraseInitTypeDef FlashEraseInit;
	HAL_StatusTypeDef FlashStatus = HAL_OK;
	uint32_t SectorError = 0;
	uint32_t addr = 0;
	uint32_t endaddr = 0;

	if((WriteAddress < FMC_FLASH_BASE) || ( WriteAddress + length >= FMC_FLASH_END) || (length <= 0) ) {
		printf("Write Address Wrong");
		return;
	}
	// 清除flash异常状态标志
	  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
	// 解锁flash
	HAL_FLASH_Unlock();

	addr = WriteAddress; // 起始地址
	endaddr = WriteAddress + length; // 结束地址


	while(addr < endaddr) {
		if(STMFLASH_ReadWord(addr) != 0XFFFFFFFF) {
			FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; // // 扇区擦除FLASH_TYPEERASE_SECTORS，块擦除FLASH_TYPEERASE_MASSERASE
			FlashEraseInit.Sector = GetSector(addr);   // 要擦除的初始扇区地址
			FlashEraseInit.NbSectors = 1; // 擦除扇区数
			FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 电压范围
			if(HAL_FLASHEx_Erase(&FlashEraseInit, &SectorError) != HAL_OK) {
				printf("Sector Erase failed!\r\n");
				break;
			}
			addr = WriteAddress + 0X4000;
		} else {
			addr += 1;
		}
	}
	FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成

	addr = WriteAddress;
	if(FlashStatus == HAL_OK) {
		while(addr < endaddr) {
			if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr, *data)!=HAL_OK) {
				break; // 写入异常
			}
			addr++;
			data++;
		}
	}
    // 重新上锁flash
    HAL_FLASH_Lock();
}
